package com.fl.ui;

import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.ToolTipManager;
import javax.swing.UIManager;
import javax.swing.border.AbstractBorder;

import org.apache.log4j.Logger;
import org.jb2011.lnf.beautyeye.widget.N9ComponentFactory;

import com.fl.util.IconUtil;

public class WorkUI extends JPanel {

	private static Logger log = Logger.getLogger(WorkUI.class);

	/** The demos. */
	String[] subUIs = {"SchedulerUI","DownloadUI","DESUI"};

	/**
	 * Load demos.
	 */
	void loadSubUIs() {
		for (int i = 0; i < subUIs.length; i++) {
			loadSubUI(subUIs[i]);
		}
	}

	// Possible Look & Feels
	// private static final String mac =
	// "com.sun.java.swing.plaf.mac.MacLookAndFeel";
	/** The Constant metal. */
	private static final String metal = "javax.swing.plaf.metal.MetalLookAndFeel";
	// private static final String motif =
	// "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
	/** The Constant windows. */
	private static final String windows = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";

	/** The Constant gtk. */
	private static final String gtk = "org.jb2011.lnf.windows2.Windows2LookAndFeel";

	// The current Look & Feel
	/** The current look and feel. */
	private static String currentLookAndFeel = metal;

	// List of demos
	/** The demos list. */
	private ArrayList<SubUIModule> uiList = new ArrayList<SubUIModule>();

	// The preferred size of the demo
	/** The Constant PREFERRED_WIDTH. */
	private static final int PREFERRED_WIDTH = 720;

	/** The Constant PREFERRED_HEIGHT. */
	private static final int PREFERRED_HEIGHT = 640;

	// Box spacers
	/** The HGAP. */
	private Dimension HGAP = new Dimension(1, 5);

	/** The VGAP. */
	private Dimension VGAP = new Dimension(5, 1);

	// Resource bundle for internationalized and accessible text
	/** The bundle. */
	private ResourceBundle bundle = null;

	// A place to hold on to the visible demo
	/** The current demo. */
	private SubUIModule currentUI = null;

	/** The demo panel. */
	private JPanel subUIPanel = null;

	// About Box
	/** The about box. */
	private JDialog aboutBox = null;

	// Status Bar
	/** The status field. */
	private JLabel statusField = null;

	// Tool Bar
	/** The toolbar. */
	private ToggleButtonToolBar toolbar = null;

	/** The toolbar group. */
	private ButtonGroup toolbarGroup = new ButtonGroup();

	// Menus
	/** The menu bar. */
	private JMenuBar menuBar = null;

	/** The options menu. */
	private JMenu optionsMenu = null;

	// Used only if swingset is an application
	/** The frame. */
	private JFrame frame = null;

	// To debug or not to debug, that is the question
	/** The DEBUG. */
	private boolean DEBUG = true;

	/** The debug counter. */
	private int debugCounter = 0;

	// The tab pane that holds the demo
	/** The tabbed pane. */
	// private JTabbedPane tabbedPane = null;

	/** The demo src pane. */
	// private JEditorPane demoSrcPane = null;

	// contentPane cache, saved from the applet or application frame
	/** The content pane. */
	Container contentPane = null;

	// number of swingsets - for multiscreen
	// keep track of the number of SwingSets created - we only want to exit
	// the program when the last one has been closed.
	/** The num s ss. */
	private static int numSSs = 0;

	/** The swing sets. */
	private static Vector<WorkUI> swingSets = new Vector<WorkUI>();

	/** The drag enabled. */
	private boolean dragEnabled = false;

	/**
	 * SwingSet2 Constructor.
	 * 
	 * @param applet
	 *            the applet
	 * @param gc
	 *            the gc
	 */
	public WorkUI(GraphicsConfiguration gc) {
		// Note that applet may be null if this is started as an application

		if (!isApplet()) {
			frame = createFrame(gc);
		}

		// set the layout
		setLayout(new BorderLayout());

		// set the preferred size of the demo
		setPreferredSize(new Dimension(PREFERRED_WIDTH, PREFERRED_HEIGHT));

		initializeUI();
		preloadFirstUI();

		// Show the demo. Must do this on the GUI thread using invokeLater.
		SwingUtilities.invokeLater(new Runnable() {
			public void run() {
				showWorkUI();
			}
		});

		// Start loading the rest of the demo in the background
		DemoLoadThread demoLoader = new DemoLoadThread(this);
		demoLoader.start();

		setStatus("感谢使用云备份系统。");
	}

	// *******************************************************
	// *************** Demo Loading Methods ******************
	// *******************************************************

	/**
	 * Initialize demo.
	 */
	public void initializeUI() {
		JPanel top = new JPanel();
		top.setLayout(new BorderLayout());

		this.setBorder(BorderFactory.createEmptyBorder(2, 0, 4, 0));// 2,2,4,2));

		add(top, BorderLayout.NORTH);

		menuBar = createMenus();

		if (isApplet()) {
			// applet.setJMenuBar(menuBar);
		} else {
			frame.setJMenuBar(menuBar);
		}

		// creates popup menu accessible via keyboard

		ToolBarPanel toolbarPanel = new ToolBarPanel();
		toolbarPanel.setLayout(new BorderLayout());
		toolbar = new ToggleButtonToolBar();
		toolbarPanel.add(toolbar, BorderLayout.CENTER);
		top.add(toolbarPanel, BorderLayout.SOUTH);
		toolbarPanel.addContainerListener(toolbarPanel);

		// tabbedPane = new JTabbedPane();
		// add(tabbedPane, BorderLayout.CENTER);
		// tabbedPane.getModel().addChangeListener(new TabListener());

		statusField = new JLabel("");
		// statusField.setEditable(false);
		JPanel hinePanel = new JPanel(new BorderLayout());// add by jb2011
		JLabel hintLabel = N9ComponentFactory.createLabel_style1("系统状态");
		hinePanel.add(hintLabel, BorderLayout.WEST);
		statusField.setBorder(BorderFactory.createEmptyBorder(2, 4, 2, 4));
		hinePanel.add(statusField, BorderLayout.CENTER);
		hinePanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 0, 4));
		add(hinePanel, BorderLayout.SOUTH);

		subUIPanel = new JPanel();
		subUIPanel.setLayout(new BorderLayout());
		// modified by jb2011
		// demoPanel.setBorder(new EtchedBorder());
		subUIPanel.setBorder(new UIPanelBorder());
		add(subUIPanel, BorderLayout.CENTER);
		// tabbedPane.addTab("Hi There!", demoPanel);

		// Add html src code viewer
		// demoSrcPane = new JEditorPane("text/html",
		// getString("SourceCode.loading"));
		// demoSrcPane.setEditable(false);

	}

	/**
	 * Create menus.
	 * 
	 * @return the j menu bar
	 */
	public JMenuBar createMenus() {
		JMenuItem mi;
		// ***** create the menubar ****
		JMenuBar menuBar = new JMenuBar();
		menuBar.getAccessibleContext().setAccessibleName("");

		// ***** create File menu
		JMenu fileMenu = (JMenu) menuBar.add(new JMenu(
				getString("FileMenu.file_label")));
		fileMenu.setMnemonic(getMnemonic("FileMenu.file_mnemonic"));
		fileMenu.getAccessibleContext().setAccessibleDescription(
				getString("FileMenu.accessible_description"));

		fileMenu.addSeparator();

		createMenuItem(fileMenu, "FileMenu.open_label",
				"FileMenu.open_mnemonic",
				"FileMenu.open_accessible_description", null);

		createMenuItem(fileMenu, "FileMenu.save_label",
				"FileMenu.save_mnemonic",
				"FileMenu.save_accessible_description", null);

		createMenuItem(fileMenu, "FileMenu.save_as_label",
				"FileMenu.save_as_mnemonic",
				"FileMenu.save_as_accessible_description", null);

		if (!isApplet()) {
			fileMenu.addSeparator();

			createMenuItem(fileMenu, "FileMenu.exit_label",
					"FileMenu.exit_mnemonic",
					"FileMenu.exit_accessible_description",
					new ExitAction(this));
		}

		// Create these menu items for the first SwingSet only.
		if (numSSs == 0) {

			// ***** create the options menu
			optionsMenu = (JMenu) menuBar.add(new JMenu(
					getString("OptionsMenu.options_label")));
			optionsMenu
					.setMnemonic(getMnemonic("OptionsMenu.options_mnemonic"));
			optionsMenu.getAccessibleContext().setAccessibleDescription(
					getString("OptionsMenu.options_accessible_description"));

			// ***** create tool tip submenu item.
			mi = createCheckBoxMenuItem(optionsMenu,
					"OptionsMenu.tooltip_label",
					"OptionsMenu.tooltip_mnemonic",
					"OptionsMenu.tooltip_accessible_description",
					new ToolTipAction());
			mi.setSelected(true);

			// ***** create drag support submenu item.
			createCheckBoxMenuItem(optionsMenu,
					"OptionsMenu.dragEnabled_label",
					"OptionsMenu.dragEnabled_mnemonic",
					"OptionsMenu.dragEnabled_accessible_description",
					new DragSupportAction());

		}

		// ***** create the multiscreen menu, if we have multiple screens
		if (!isApplet()) {
			GraphicsDevice[] screens = GraphicsEnvironment
					.getLocalGraphicsEnvironment().getScreenDevices();
			if (screens.length > 1) {

				JMenu multiScreenMenu = (JMenu) menuBar.add(new JMenu(
						getString("MultiMenu.multi_label")));

				multiScreenMenu
						.setMnemonic(getMnemonic("MultiMenu.multi_mnemonic"));
				multiScreenMenu
						.getAccessibleContext()
						.setAccessibleDescription(
								getString("MultiMenu.multi_accessible_description"));

				createMultiscreenMenuItem(multiScreenMenu,
						MultiScreenAction.ALL_SCREENS);
				for (int i = 0; i < screens.length; i++) {
					createMultiscreenMenuItem(multiScreenMenu, i);
				}
			}
		}

		return menuBar;
	}

	/**
	 * Create a checkbox menu menu item.
	 * 
	 * @param menu
	 *            the menu
	 * @param label
	 *            the label
	 * @param mnemonic
	 *            the mnemonic
	 * @param accessibleDescription
	 *            the accessible description
	 * @param action
	 *            the action
	 * @return the j menu item
	 */
	private JMenuItem createCheckBoxMenuItem(JMenu menu, String label,
			String mnemonic, String accessibleDescription, Action action) {
		JCheckBoxMenuItem mi = (JCheckBoxMenuItem) menu
				.add(new JCheckBoxMenuItem(getString(label)));
		mi.setMnemonic(getMnemonic(mnemonic));
		mi.getAccessibleContext().setAccessibleDescription(
				getString(accessibleDescription));
		mi.addActionListener(action);
		return mi;
	}

	/**
	 * Create a radio button menu menu item for items that are part of a button
	 * group.
	 * 
	 * @param menu
	 *            the menu
	 * @param label
	 *            the label
	 * @param mnemonic
	 *            the mnemonic
	 * @param accessibleDescription
	 *            the accessible description
	 * @param action
	 *            the action
	 * @param buttonGroup
	 *            the button group
	 * @return the j menu item
	 */
	private JMenuItem createButtonGroupMenuItem(JMenu menu, String label,
			String mnemonic, String accessibleDescription, Action action,
			ButtonGroup buttonGroup) {
		JRadioButtonMenuItem mi = (JRadioButtonMenuItem) menu
				.add(new JRadioButtonMenuItem(getString(label)));
		buttonGroup.add(mi);
		mi.setMnemonic(getMnemonic(mnemonic));
		mi.getAccessibleContext().setAccessibleDescription(
				getString(accessibleDescription));
		mi.addActionListener(action);
		return mi;
	}

	/**
	 * Creates a generic menu item.
	 * 
	 * @param menu
	 *            the menu
	 * @param label
	 *            the label
	 * @param mnemonic
	 *            the mnemonic
	 * @param accessibleDescription
	 *            the accessible description
	 * @param action
	 *            the action
	 * @return the j menu item
	 */
	public JMenuItem createMenuItem(JMenu menu, String label, String mnemonic,
			String accessibleDescription, Action action) {
		JMenuItem mi = (JMenuItem) menu.add(new JMenuItem(getString(label)));

		// mi.setBorder(BorderFactory.createEmptyBorder());
		mi.setMnemonic(getMnemonic(mnemonic));
		mi.getAccessibleContext().setAccessibleDescription(
				getString(accessibleDescription));
		mi.addActionListener(action);
		if (action == null) {
			mi.setEnabled(false);
		}
		return mi;
	}

	/**
	 * Creates a multi-screen menu item.
	 * 
	 * @param menu
	 *            the menu
	 * @param screen
	 *            the screen
	 * @return the j menu item
	 */
	public JMenuItem createMultiscreenMenuItem(JMenu menu, int screen) {
		JMenuItem mi = null;
		if (screen == MultiScreenAction.ALL_SCREENS) {
			mi = (JMenuItem) menu.add(new JMenuItem(
					getString("MultiMenu.all_label")));
			mi.setMnemonic(getMnemonic("MultiMenu.all_mnemonic"));
			mi.getAccessibleContext().setAccessibleDescription(
					getString("MultiMenu.all_accessible_description"));
		} else {
			mi = (JMenuItem) menu.add(new JMenuItem(
					getString("MultiMenu.single_label") + " " + screen));
			mi.setMnemonic(KeyEvent.VK_0 + screen);
			mi.getAccessibleContext().setAccessibleDescription(
					getString("MultiMenu.single_accessible_description") + " "
							+ screen);

		}
		mi.addActionListener(new MultiScreenAction(this, screen));
		return mi;
	}

	/**
	 * Load the first demo. This is done separately from the remaining demos so
	 * that we can get SwingSet2 up and available to the user quickly.
	 */
	public void preloadFirstUI() {
		SubUIModule ui = addUI(new WelcomeUI(this));
		setSubUI(ui);
	}

	/**
	 * Add a demo to the toolbar.
	 * 
	 * @param ui
	 *            the demo
	 * @return the demo module
	 */
	public SubUIModule addUI(SubUIModule ui) {
		uiList.add(ui);
		if (dragEnabled) {
			ui.updateDragEnabled(true);
		}
		// do the following on the gui thread
		SwingUtilities.invokeLater(new SwingSetRunnable(this, ui) {
			public void run() {
				SwitchToUIAction action = new SwitchToUIAction(swingset,
						(SubUIModule) obj);
				JToggleButton tb = swingset.getToolBar()
						.addToggleButton(action);
				swingset.getToolBarGroup().add(tb);
				if (swingset.getToolBarGroup().getSelection() == null) {
					tb.setSelected(true);
				}
				// tb.setText(null);
				tb.setIcon(null);
				tb.setToolTipText(((SubUIModule) obj).getToolTip());

			}
		});
		return ui;
	}

	/**
	 * Sets the current demo.
	 * 
	 * @param subUI
	 *            the new demo
	 */
	public void setSubUI(SubUIModule subUI) {
		currentUI = subUI;

		// Ensure panel's UI is current before making visible
		JComponent currentUIPanel = subUI.getSubUIPanel();

		subUIPanel.removeAll();
		subUIPanel.add(currentUIPanel, BorderLayout.CENTER);

	}

	/**
	 * Bring up the SwingSet2 demo by showing the frame (only applicable if
	 * coming up as an application, not an applet);.
	 */
	public void showWorkUI() {
		if (!isApplet() && getFrame() != null) {
			// put swingset in a frame and show it
			JFrame f = getFrame();
			f.setTitle("数据云备份");
			f.getContentPane().add(this, BorderLayout.CENTER);
			f.pack();

			Rectangle screenRect = f.getGraphicsConfiguration().getBounds();
			Insets screenInsets = Toolkit.getDefaultToolkit().getScreenInsets(
					f.getGraphicsConfiguration());

			// Make sure we don't place the demo off the screen.
			int centerWidth = screenRect.width < f.getSize().width ? screenRect.x
					: screenRect.x + screenRect.width / 2 - f.getSize().width
							/ 2;
			int centerHeight = screenRect.height < f.getSize().height ? screenRect.y
					: screenRect.y + screenRect.height / 2 - f.getSize().height
							/ 2;

			centerHeight = centerHeight < screenInsets.top ? screenInsets.top
					: centerHeight;

			f.setLocation(centerWidth, centerHeight);
			f.show();
			numSSs++;
			swingSets.add(this);
		}
	}

	// *******************************************************
	// ****************** Utility Methods ********************
	// *******************************************************

	/**
	 * Loads a demo from a classname.
	 * 
	 * @param classname
	 *            the classname
	 */
	void loadSubUI(String classname) {
		SubUIModule ui = null;
		try {
			Class uiClass = Class.forName("com.fl.ui." + classname);
			Constructor uiConstructor = uiClass
					.getConstructor(new Class[] { WorkUI.class });
			ui = (SubUIModule) uiConstructor.newInstance(new Object[] { this });
			addUI(ui);
		} catch (Exception e) {
			log.error(e);
			System.out.println("Error occurred loading ui: " + "com.fl.ui."
					+ classname);
		}
	}

	/**
	 * Determines if this is an applet or application.
	 * 
	 * @return true, if is applet
	 */
	public boolean isApplet() {
		return false;
	}

	/**
	 * Returns the frame instance.
	 * 
	 * @return the frame
	 */
	public JFrame getFrame() {
		return frame;
	}

	/**
	 * Returns the menubar.
	 * 
	 * @return the menu bar
	 */
	public JMenuBar getMenuBar() {
		return menuBar;
	}

	/**
	 * Returns the toolbar.
	 * 
	 * @return the tool bar
	 */
	public ToggleButtonToolBar getToolBar() {
		return toolbar;
	}

	/**
	 * Returns the toolbar button group.
	 * 
	 * @return the tool bar group
	 */
	public ButtonGroup getToolBarGroup() {
		return toolbarGroup;
	}

	/**
	 * Returns the content pane wether we're in an applet or application.
	 * 
	 * @return the content pane
	 */
	public Container getContentPane() {
		if (contentPane == null) {
			if (getFrame() != null) {
				contentPane = getFrame().getContentPane();
			}
		}
		return contentPane;
	}

	/**
	 * Create a frame for SwingSet2 to reside in if brought up as an
	 * application.
	 * 
	 * @param gc
	 *            the gc
	 * @return the j frame
	 */
	public static JFrame createFrame(GraphicsConfiguration gc) {
		JFrame frame = new JFrame(gc);
		if (numSSs == 0) {
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		} else {
			WindowListener l = new WindowAdapter() {
				public void windowClosing(WindowEvent e) {
					numSSs--;
					swingSets.remove(this);
				}
			};
			frame.addWindowListener(l);
		}

		frame.setMinimumSize(new Dimension(100, 100));
		return frame;
	}

	/**
	 * Set the status.
	 * 
	 * @param s
	 *            the new status
	 */
	public void setStatus(String s) {
		// do the following on the gui thread
		SwingUtilities.invokeLater(new SwingSetRunnable(this, s) {
			public void run() {
				swingset.statusField.setText((String) obj);
			}
		});
	}

	/**
	 * This method returns a string from the demo's resource bundle.
	 * 
	 * @param key
	 *            the key
	 * @return the string
	 */
	public String getString(String key) {
		String value = null;
		try {
			value = getResourceBundle().getString(key);
		} catch (MissingResourceException e) {
			System.out
					.println("java.util.MissingResourceException: Couldn't find value for: "
							+ key);
		}
		if (value == null) {
			value = "Could not find resource: " + key + "  ";
		}
		return value;
	}

	/**
	 * Sets the drag enabled.
	 * 
	 * @param dragEnabled
	 *            the new drag enabled
	 */
	void setDragEnabled(boolean dragEnabled) {
		if (dragEnabled == this.dragEnabled) {
			return;
		}

		this.dragEnabled = dragEnabled;

		for (SubUIModule dm : uiList) {
			dm.updateDragEnabled(dragEnabled);
		}

	}

	/**
	 * Checks if is drag enabled.
	 * 
	 * @return true, if is drag enabled
	 */
	boolean isDragEnabled() {
		return dragEnabled;
	}

	/**
	 * Returns the resource bundle associated with this demo. Used to get
	 * accessable and internationalized strings.
	 * 
	 * @return the resource bundle
	 */
	public ResourceBundle getResourceBundle() {
		if (bundle == null) {
			bundle = ResourceBundle.getBundle("resources.swingset");
		}
		return bundle;
	}

	/**
	 * Returns a mnemonic from the resource bundle. Typically used as keyboard
	 * shortcuts in menu items.
	 * 
	 * @param key
	 *            the key
	 * @return the mnemonic
	 */
	public char getMnemonic(String key) {
		return (getString(key)).charAt(0);
	}

	/**
	 * Creates an icon from an image contained in the "images" directory.
	 * 
	 * @param filename
	 *            the filename
	 * @param description
	 *            the description
	 * @return the image icon
	 */
	public ImageIcon createImageIcon(String filename, String description) {
		// String path = "/resources/images/" + filename;
		// return new ImageIcon(getClass().getResource(path));
		return IconUtil.getImageIcon(filename);
	}

	/**
	 * If DEBUG is defined, prints debug information out to std ouput.
	 * 
	 * @param s
	 *            the s
	 */
	public void debug(String s) {
		if (DEBUG) {
			System.out.println((debugCounter++) + ": " + s);
		}
	}

	/**
	 * Update this swing set.
	 */
	private void updateThisSwingSet() {
		if (isApplet()) {
			// SwingUtilities.updateComponentTreeUI(getApplet());
		} else {
			JFrame frame = getFrame();
			if (frame == null) {
				SwingUtilities.updateComponentTreeUI(this);
			} else {
				SwingUtilities.updateComponentTreeUI(frame);
			}
		}

		if (aboutBox != null) {
			SwingUtilities.updateComponentTreeUI(aboutBox);
		}
	}

	/**
	 * Sets the current L&F on each demo module.
	 */
	public void updateLookAndFeel() {
		try {
			System.out.println("!!currentLookAndFeel=" + currentLookAndFeel);
			UIManager.setLookAndFeel(currentLookAndFeel);
			if (isApplet()) {
				updateThisSwingSet();
			} else {
				for (WorkUI ss : swingSets) {
					ss.updateThisSwingSet();
				}
			}
		} catch (Exception ex) {
			System.out.println("Failed loading L&F: " + currentLookAndFeel);
			System.out.println(ex);
		}
	}

	// *******************************************************
	// ************** ToggleButtonToolbar *****************
	// *******************************************************
	/** The zero insets. */
	static Insets zeroInsets = new Insets(3, 2, 3, 2);

	/**
	 * The Class ToggleButtonToolBar.
	 */
	protected class ToggleButtonToolBar extends JToolBar {

		/**
		 * Instantiates a new toggle button tool bar.
		 */
		public ToggleButtonToolBar() {
			super();

			this.setFloatable(true);
		}

		/**
		 * Adds the toggle button.
		 * 
		 * @param a
		 *            the a
		 * @return the j toggle button
		 */
		JToggleButton addToggleButton(Action a) {
			JToggleButton tb = new JToggleButton(
					(String) a.getValue(Action.NAME), null
			// (Icon)a.getValue(Action.SMALL_ICON)
			);
			// tb.setMargin(zeroInsets);
			// tb.setText(null);
			tb.setEnabled(a.isEnabled());
			tb.setToolTipText((String) a.getValue(Action.SHORT_DESCRIPTION));
			tb.setAction(a);
			add(tb);
			return tb;
		}
	}

	// *******************************************************
	// ********* ToolBar Panel / Docking Listener ***********
	// *******************************************************
	/**
	 * The Class ToolBarPanel.
	 */
	class ToolBarPanel extends JPanel implements ContainerListener {

		/*
		 * (non-Javadoc)
		 * 
		 * @see javax.swing.JComponent#contains(int, int)
		 */
		public boolean contains(int x, int y) {
			Component c = getParent();
			if (c != null) {
				Rectangle r = c.getBounds();
				return (x >= 0) && (x < r.width) && (y >= 0) && (y < r.height);
			} else {
				return super.contains(x, y);
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.awt.event.ContainerListener#componentAdded(java.awt.event.
		 * ContainerEvent)
		 */
		public void componentAdded(ContainerEvent e) {
			Container c = e.getContainer().getParent();
			if (c != null) {
				c.getParent().validate();
				c.getParent().repaint();
			}
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ContainerListener#componentRemoved(java.awt.event.
		 * ContainerEvent)
		 */
		public void componentRemoved(ContainerEvent e) {
			Container c = e.getContainer().getParent();
			if (c != null) {
				c.getParent().validate();
				c.getParent().repaint();
			}
		}
	}

	// *******************************************************
	// ****************** Runnables ***********************
	// *******************************************************

	/**
	 * Generic SwingSet2 runnable. This is intended to run on the AWT gui event
	 * thread so as not to muck things up by doing gui work off the gui thread.
	 * Accepts a SwingSet2 and an Object as arguments, which gives subtypes of
	 * this class the two "must haves" needed in most runnables for this demo.
	 */
	class SwingSetRunnable implements Runnable {

		/** The swingset. */
		protected WorkUI swingset;

		/** The obj. */
		protected Object obj;

		/**
		 * Instantiates a new swing set runnable.
		 * 
		 * @param swingset
		 *            the swingset
		 * @param obj
		 *            the obj
		 */
		public SwingSetRunnable(WorkUI swingset, Object obj) {
			this.swingset = swingset;
			this.obj = obj;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Runnable#run()
		 */
		public void run() {
		}
	}

	// *******************************************************
	// ******************** Actions ***********************
	// *******************************************************

	/**
	 * The Class SwitchToDemoAction.
	 */
	public class SwitchToUIAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/** The demo. */
		SubUIModule ui;

		/**
		 * Instantiates a new switch to demo action.
		 * 
		 * @param swingset
		 *            the swingset
		 * @param ui
		 *            the demo
		 */
		public SwitchToUIAction(WorkUI swingset, SubUIModule ui) {
			super(ui.getName(), ui.getIcon());
			this.swingset = swingset;
			this.ui = ui;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			swingset.setSubUI(ui);
			validate();
			repaint();
			
		}
	}

	/**
	 * The Class OkAction.
	 */
	class OkAction extends AbstractAction {

		/** The about box. */
		JDialog aboutBox;

		/**
		 * Instantiates a new ok action.
		 * 
		 * @param aboutBox
		 *            the about box
		 */
		protected OkAction(JDialog aboutBox) {
			super("OkAction");
			this.aboutBox = aboutBox;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			aboutBox.setVisible(false);
		}
	}

	/**
	 * The Class ActivatePopupMenuAction.
	 */
	class ActivatePopupMenuAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/** The popup. */
		JPopupMenu popup;

		/**
		 * Instantiates a new activate popup menu action.
		 * 
		 * @param swingset
		 *            the swingset
		 * @param popup
		 *            the popup
		 */
		protected ActivatePopupMenuAction(WorkUI swingset, JPopupMenu popup) {
			super("ActivatePopupMenu");
			this.swingset = swingset;
			this.popup = popup;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			Dimension invokerSize = getSize();
			Dimension popupSize = popup.getPreferredSize();
			popup.show(swingset, (invokerSize.width - popupSize.width) / 2,
					(invokerSize.height - popupSize.height) / 2);
		}
	}

	// Turns on all possible auditory feedback
	/**
	 * The Class OnAudioAction.
	 */
	class OnAudioAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/**
		 * Instantiates a new on audio action.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		protected OnAudioAction(WorkUI swingset) {
			super("Audio On");
			this.swingset = swingset;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			// * Jack Jiang ��2012-09-11��ע�͵�
			// UIManager.put("AuditoryCues.playList",
			// UIManager.get("AuditoryCues.allAuditoryCues"));
			// swingset.updateLookAndFeel();
		}
	}

	// Turns on the default amount of auditory feedback
	/**
	 * The Class DefaultAudioAction.
	 */
	class DefaultAudioAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/**
		 * Instantiates a new default audio action.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		protected DefaultAudioAction(WorkUI swingset) {
			super("Audio Default");
			this.swingset = swingset;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			// * Jack Jiang ��2012-09-11��ע�͵�
			// UIManager.put("AuditoryCues.playList",
			// UIManager.get("AuditoryCues.defaultCueList"));
			// swingset.updateLookAndFeel();
		}
	}

	// Turns off all possible auditory feedback
	/**
	 * The Class OffAudioAction.
	 */
	class OffAudioAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/**
		 * Instantiates a new off audio action.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		protected OffAudioAction(WorkUI swingset) {
			super("Audio Off");
			this.swingset = swingset;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			// UIManager.put("AuditoryCues.playList",
			// UIManager.get("AuditoryCues.noAuditoryCues"));
			// swingset.updateLookAndFeel();
		}
	}

	// Turns on or off the tool tips for the demo.
	/**
	 * The Class ToolTipAction.
	 */
	class ToolTipAction extends AbstractAction {

		/**
		 * Instantiates a new tool tip action.
		 */
		protected ToolTipAction() {
			super("ToolTip Control");
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			boolean status = ((JCheckBoxMenuItem) e.getSource()).isSelected();
			ToolTipManager.sharedInstance().setEnabled(status);
		}
	}

	/**
	 * The Class DragSupportAction.
	 */
	class DragSupportAction extends AbstractAction {

		/**
		 * Instantiates a new drag support action.
		 */
		protected DragSupportAction() {
			super("DragSupport Control");
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			boolean dragEnabled = ((JCheckBoxMenuItem) e.getSource())
					.isSelected();
			if (isApplet()) {
				setDragEnabled(dragEnabled);
			} else {
				for (WorkUI ss : swingSets) {
					ss.setDragEnabled(dragEnabled);
				}
			}
		}
	}

	/**
	 * The Class ExitAction.
	 */
	class ExitAction extends AbstractAction {

		/** The swingset. */
		WorkUI swingset;

		/**
		 * Instantiates a new exit action.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		protected ExitAction(WorkUI swingset) {
			super("ExitAction");
			this.swingset = swingset;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			System.exit(0);
		}
	}

	/**
	 * The Class MultiScreenAction.
	 */
	class MultiScreenAction extends AbstractAction {

		/** The Constant ALL_SCREENS. */
		static final int ALL_SCREENS = -1;

		/** The screen. */
		int screen;

		/**
		 * Instantiates a new multi screen action.
		 * 
		 * @param swingset
		 *            the swingset
		 * @param screen
		 *            the screen
		 */
		protected MultiScreenAction(WorkUI swingset, int screen) {
			super("MultiScreenAction");
			this.screen = screen;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
		 * )
		 */
		public void actionPerformed(ActionEvent e) {
			GraphicsDevice[] gds = GraphicsEnvironment
					.getLocalGraphicsEnvironment().getScreenDevices();
			if (screen == ALL_SCREENS) {
				for (int i = 0; i < gds.length; i++) {
					WorkUI swingset = new WorkUI(
							gds[i].getDefaultConfiguration());
					swingset.setDragEnabled(dragEnabled);
				}
			} else {
				WorkUI swingset = new WorkUI(
						gds[screen].getDefaultConfiguration());
				swingset.setDragEnabled(dragEnabled);
			}
		}
	}

	// *******************************************************
	// ********************** Misc *************************
	// *******************************************************

	/**
	 * The Class DemoLoadThread.
	 */
	class DemoLoadThread extends Thread {

		/** The swingset. */
		WorkUI swingset;

		/**
		 * Instantiates a new demo load thread.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		public DemoLoadThread(WorkUI swingset) {
			this.swingset = swingset;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see java.lang.Thread#run()
		 */
		public void run() {
			swingset.loadSubUIs();
		}
	}

	/**
	 * The Class AboutPanel.
	 */
	class AboutPanel extends JPanel {

		/** The aboutimage. */
		ImageIcon aboutimage = null;

		/** The swingset. */
		WorkUI swingset = null;

		/**
		 * Instantiates a new about panel.
		 * 
		 * @param swingset
		 *            the swingset
		 */
		public AboutPanel(WorkUI swingset) {
			this.swingset = swingset;
			aboutimage = swingset.createImageIcon("About.jpg",
					"AboutBox.accessible_description");
			setOpaque(false);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see javax.swing.JComponent#paint(java.awt.Graphics)
		 */
		public void paint(Graphics g) {
			aboutimage.paintIcon(this, g, 0, 0);
			super.paint(g);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see javax.swing.JComponent#getPreferredSize()
		 */
		public Dimension getPreferredSize() {
			return new Dimension(aboutimage.getIconWidth(),
					aboutimage.getIconHeight());
		}
	}

	// -------------------------------------------------------------
	/**
	 * The Class DemoPanelBorder.
	 */
	private class UIPanelBorder extends AbstractBorder {

		/**
		 * Instantiates a new demo panel border.
		 */
		public UIPanelBorder() {
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * javax.swing.border.AbstractBorder#paintBorder(java.awt.Component,
		 * java.awt.Graphics, int, int, int, int)
		 */
		public void paintBorder(Component c, Graphics g, int x, int y,
				int width, int height) {
			// g.drawLine(x,y, widthheight); // draw top
			// g.drawLine(x,y, x,height-1); // draw left
			// g.drawLine(width-1,y, width-1,height-1); // draw right

			Stroke oldStroke = ((Graphics2D) g).getStroke();
			Stroke sroke = new BasicStroke(1, BasicStroke.CAP_BUTT,
					BasicStroke.JOIN_BEVEL, 0, new float[] { 1, 2 }, 0);// ʵ�ߣ��հ�
			((Graphics2D) g).setStroke(sroke);

			g.setColor(new Color(200, 200, 200));
			g.drawLine(x, height - 2, width - 1, height - 2); // draw bottom1

			g.setColor(Color.white);
			g.drawLine(x, height - 1, width - 1, height - 1);// draw bottom2

			((Graphics2D) g).setStroke(oldStroke);
		}

		//
		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * javax.swing.border.AbstractBorder#getBorderInsets(java.awt.Component)
		 */
		public Insets getBorderInsets(Component c) {
			return new Insets(0, 0, 2, 0);
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see
		 * javax.swing.border.AbstractBorder#getBorderInsets(java.awt.Component,
		 * java.awt.Insets)
		 */
		public Insets getBorderInsets(Component c, Insets insets) {
			// insets.top = insets.left = insets.bottom = insets.right = 1;
			return getBorderInsets(c);// insets;
		}
	}
}
